#pragma once

#include "LeDocumentObject/IDocumentObjectFactory.h"

#include <QMap>

struct MetaEnumValue
{
    MetaEnumValue() {}
    MetaEnumValue(const QString &aText, const QString &anIconName)
        : text(aText)
        , iconName(anIconName)
    {}
    MetaEnumValue(const MetaEnumValue &other)
        : text(other.text)
        , iconName(other.iconName)
    {}
    QString text;
    QString iconName;
};

struct MetaEnum
{
    MetaEnum() {}
    explicit MetaEnum(const QMap<int, MetaEnumValue> &aValueMap)
        : valueMap(aValueMap)
    {}
    MetaEnum(const MetaEnum &other)
        : valueMap(other.valueMap)
    {}

    QMap<int, MetaEnumValue> valueMap;
};

class DocumentObjectFactory : public LDO::IDocumentObjectFactory
{
    Q_OBJECT
    Q_DISABLE_COPY(DocumentObjectFactory)

public:
    explicit DocumentObjectFactory(QObject *parent = nullptr);

    template<class T>
    void registerMetaClass()
    {
        int id = qRegisterMetaType<T*>();
        m_creators.insert(id, []() -> LDO::IDocumentObject* {
            return new T();
        });
    }

    template<typename T>
    void registerMetaEnum(const MetaEnum &metaEnum)
    {
        int id = qRegisterMetaType<T>();
        m_enums.insert(id, metaEnum);
    }

    template<typename F>
    void registerMetaFlag(const MetaEnum &metaEnum)
    {
        int id = qRegisterMetaType<F>();
        m_enums.insert(id, metaEnum);
    }

private:
    typedef LDO::IDocumentObject* (*CreatorFunc)();
    QMap<int, CreatorFunc> m_creators;
    QMap<int, MetaEnum> m_enums;

    // IDocumentObjectFactory interface
public:
    virtual QList<int> objectTypeIds() const override;
    virtual LDO::IDocumentObject *createObject(int typeId) const override;
    virtual QString typeName(int typeId) const override;
    virtual QString iconName(int typeId, const LDO::IDocumentObject *object) const override;
};
